package com.xiyoufang.mycli.nginx;

import com.jfinal.template.Engine;
import com.xiyoufang.mycli.Utils;
import picocli.CommandLine;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;

/**
 * Created by 席有芳 on 2021/11/27.
 * 用于生成nginx反向代理的配置
 *
 * @author 席有芳
 */
@CommandLine.Command(name = "proxy", description = "反向代理")
public class Proxy implements Callable<Integer> {

    /**
     * 帮助信息
     */
    @CommandLine.Option(names = {"-h", "--help"}, usageHelp = true)
    private boolean help;
    /**
     * 服务名称
     */
    @CommandLine.Option(names = {"-s", "--serverName"}, description = "域名, 例如: www.xiyoufang.com", interactive = true, echo = true, required = true)
    private String serverName;
    /**
     * 代理地址
     */
    @CommandLine.Option(names = {"-p", "--proxyServer"}, description = "代理, 例如: 127.0.0.1:8082", interactive = true, echo = true, required = true)
    private String proxyServer;
    /**
     * SSL
     */
    @CommandLine.Option(names = {"-ssl"}, description = "是否启用ssl")
    private boolean ssl;

    /**
     * HTTP模板
     */
    private static final String HTTP_TEMPLATE = "server {\n" +
            "    listen       80;\n" +
            "    server_name  #(serverName);\n" +
            "    location / {\n" +
            "          proxy_set_header X-Real-IP $remote_addr;\n" +
            "          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n" +
            "          proxy_set_header Host $http_host;\n" +
            "          proxy_pass http://#(upName);\n" +
            "          proxy_http_version 1.1;\n" +
            "          proxy_set_header Upgrade $http_upgrade;\n" +
            "          proxy_set_header Connection \"upgrade\";\n" +
            "          proxy_next_upstream error;\n" +
            "    }\n" +
            "}\n" +
            "upstream #(upName) {\n" +
            "    server #(proxyServer);\n" +
            "}";

    /**
     * HTTPS模板
     */
    private static final String HTTPS_TEMPLATE = "server {\n" +
            "    listen       443 ssl;\n" +
            "    server_name  #(serverName);\n" +
            "    ssl_certificate     #(serverName).pem;\n" +
            "    ssl_certificate_key #(serverName).key;\n" +
            "    ssl_session_cache shared:SSL:1m;\n" +
            "    ssl_session_timeout  10m;\n" +
            "    ssl_ciphers HIGH:!aNULL:!MD5;\n" +
            "    ssl_prefer_server_ciphers on;\n" +
            "    location / {\n" +
            "          proxy_set_header X-Real-IP $remote_addr;\n" +
            "          proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n" +
            "          proxy_set_header Host $http_host;\n" +
            "          proxy_pass http://#(upName);\n" +
            "          proxy_http_version 1.1;\n" +
            "          proxy_set_header Upgrade $http_upgrade;\n" +
            "          proxy_set_header Connection \"upgrade\";\n" +
            "          proxy_next_upstream error;\n" +
            "    }\n" +
            "}\n" +
            "upstream #(upName) {\n" +
            "    server #(proxyServer);\n" +
            "}\n" +
            "server {\n" +
            "    listen 80;\n" +
            "    server_name #(serverName);\n" +
            "    return 301 https://$server_name$request_uri;\n" +
            "}\n";

    @Override
    public Integer call() throws Exception {
        Map<String, String> param = new HashMap<>();
        param.put("serverName", this.serverName);
        param.put("proxyServer", this.proxyServer);
        param.put("upName", "upstream" + Utils.token(5));
        System.out.println(Engine.use().getTemplateByString(ssl ? HTTPS_TEMPLATE : HTTP_TEMPLATE).renderToString(param));
        return 0;
    }
}
